package com.sc.nft.task;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.thread.ExecutorBuilder;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.sc.nft.dao.*;
import com.sc.nft.entity.*;
import com.sc.nft.enums.*;
import com.sc.nft.service.*;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.xxl.job.core.util.FileUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

@Component
@RequiredArgsConstructor
@Slf4j
public class ChainTask {
    private final UserChainInfoDao userChainInfoDao;
    private final UserChainInfoService userChainInfoService;
    private final UserCollectionDao userCollectionDao;
    private final UserCollectionChainLogDao userCollectionChainLogDao;
    private final CollectionChainInitDetailsLogService collectionChainInitDetailsLogService;
    private final DigitalCollectionDao digitalCollectionDao;
    private final ChainCallBackLogDao chainCallBackLogDao;

    /**
     * 用户注册上链
     *
     * @throws Exception
     */
    @XxlJob("userRegister")
    public void userRegister() throws Exception {
        List<UserChainInfo> userChainInfoList = userChainInfoDao.getNoRegisterUser();
        userChainInfoList.forEach(userChainInfoService::userRegister);
    }

    /**
     * 藏品上链(单个)
     *
     * @throws Exception
     */
    @XxlJob("mint")
    public void mint() throws Exception {
        List<CollectionChainInitDetailsLog> list = collectionChainInitDetailsLogService.getOneTypeListByStatusAndDealStatus(UserChainLogStatusEnum.WAIT, CollectionChainDealStatusEnum.IN_CHINA);
        list.forEach(userChainInfoService::mint);
    }

    /**
     * 藏品上链(批量)
     *
     * @throws Exception
     */
    @XxlJob("mintBatch")
    public void mintBatch() throws Exception {
        List<DigitalCollection> collectionList = digitalCollectionDao.getListByChainStatusAndContractStatus(CollectionChainStatusEnum.ON_THE_CHAIN, CollectionContractStatusEnum.DEPLOY_SUCCESS);
        for (DigitalCollection digitalCollection : collectionList) {
            //获取待上链列表
            List<CollectionChainInitDetailsLog> list = collectionChainInitDetailsLogService.metaChainInitListAndCollectionIdAndLimit(digitalCollection.getId(), UserChainLogStatusEnum.WAIT, CollectionChainDealStatusEnum.IN_CHINA, 50000);
            if (ObjectUtil.isNotNull(list) && list.size() > 0) {
                List<List<CollectionChainInitDetailsLog>> partition = ListUtil.partition(list, 100);
                for (List<CollectionChainInitDetailsLog> collectionChainInitDetailsLogs : partition) {
                    //上链逻辑
                    userChainInfoService.mintBatch(collectionChainInitDetailsLogs);
                }
            }
        }
    }

    /**
     * 同步藏品上链数量,如果上链数量等于总数量，则修改藏品状态为上链完成
     *
     * @throws Exception
     */
    @XxlJob("syncInitCollectionChainStatus")
    public void syncInitCollectionChainStatus() throws Exception {
        List<DigitalCollection> list = digitalCollectionDao.findListByChainStatus(CollectionChainStatusEnum.ON_THE_CHAIN);
        for (DigitalCollection collection : list) {
            //如果上链数量等于总数量，则修改藏品状态为上链完成
            Integer count = collectionChainInitDetailsLogService.getCountByStatusAndChainStatusAndCollectionId(UserChainLogStatusEnum.SUCCESS, CollectionChainDealStatusEnum.TRADEABLE, collection.getId());
            if (count.intValue() == collection.getSumCount().intValue()) {
                digitalCollectionDao.updateChainStatus(collection.getId(), CollectionChainStatusEnum.CHAIN_COMPLETED);
            }
        }
    }

    /**
     * 藏品交易
     *
     * @throws Exception
     */
    @XxlJob("transfer")
    public void transfer() throws Exception {
        List<UserCollectionChainLog> collectionChainLogs = userCollectionChainLogDao.getByTypeAndStatus(UserChainTypeEnum.TRANSFER, UserChainLogStatusEnum.WAIT);
        collectionChainLogs.forEach(userChainInfoService::transfer);
    }

    /**
     * 藏品回收
     * @throws Exception
     */
    @XxlJob("recycleCollection")
    public void recycleCollection() throws Exception {
        List<UserCollectionChainLog> collectionChainLogs = userCollectionChainLogDao.getByTypeAndStatus(UserChainTypeEnum.RECYCLE, UserChainLogStatusEnum.WAIT);
        collectionChainLogs.forEach(userChainInfoService::recycleCollection);
    }

    /**
     * 生态藏品销毁
     * @throws Exception
     */
    @XxlJob("ecologyDestroyCollection")
    public void ecologyDestroyCollection() throws Exception {
        List<UserCollectionChainLog> collectionChainLogs = userCollectionChainLogDao.getByTypeAndStatus(UserChainTypeEnum.ECOLOGY_DESTROY, UserChainLogStatusEnum.WAIT);
        collectionChainLogs.forEach(userChainInfoService::ecologyDestroyCollection);
    }
    /**
     * 交易池藏品销毁
     * @throws Exception
     */
    @XxlJob("tradingDestroyCollection")
    public void tradingDestroyCollection() throws Exception {
        List<UserCollectionChainLog> collectionChainLogs = userCollectionChainLogDao.getByTypeAndStatus(UserChainTypeEnum.TRADING_DESTROY, UserChainLogStatusEnum.WAIT);
        collectionChainLogs.forEach(userChainInfoService::tradingDestroyCollection);
    }


    /**
     * 质押（燕之巢）藏品销毁
     * @throws Exception
     */
    @XxlJob("pledgeDestroyCollection")
    public void pledgeDestroyCollection() throws Exception {
        List<UserCollectionChainLog> collectionChainLogs = userCollectionChainLogDao.getByTypeAndStatus(UserChainTypeEnum.PlEDGE_DESTROY, UserChainLogStatusEnum.WAIT);
        collectionChainLogs.forEach(userChainInfoService::pledgeDestroyCollection);
    }

    /**
     * 转增到玛特钱包
     * @throws Exception
     */
    @XxlJob("transferToMetaWallet")
    public void transferToMetaWallet() throws Exception {
        List<UserCollectionChainLog> collectionChainLogs = userCollectionChainLogDao.getByTypeAndStatus(UserChainTypeEnum.TO_META_WALLET, UserChainLogStatusEnum.WAIT);
        collectionChainLogs.forEach(userChainInfoService::transferToMetaWallet);
    }
    /**
     * 玛特钱包转入
     * @throws Exception
     */
    @XxlJob("transferFromMetaWallet")
    public void transferFromMetaWallet() throws Exception {
        List<UserCollectionChainLog> collectionChainLogs = userCollectionChainLogDao.getByTypeAndStatus(UserChainTypeEnum.FROM_META_WALLET, UserChainLogStatusEnum.WAIT);
        collectionChainLogs.forEach(userChainInfoService::transferFromMetaWallet);
    }

    /**
     * 藏品交易
     *
     * @throws Exception
     */
    @XxlJob("transferInit")
    public void transferInit() throws Exception {
        Long halfId = userCollectionChainLogDao.getHalfId();
        List<UserCollectionChainLog> ltId = userCollectionChainLogDao.getByTypeAndStatusLtId(UserChainTypeEnum.TRANSFER, UserChainLogStatusEnum.WAIT, halfId);
        List<List<UserCollectionChainLog>> split = CollUtil.split(ltId, 10000);
        ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(8);
        for (List<UserCollectionChainLog> userCollectionChainLogs : split) {
            threadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    log.info("线程{}开始工作", Thread.currentThread().getId());
                    userCollectionChainLogs.forEach(userChainInfoService::transfer);
                }
            });
        }
        Thread.sleep(3000);
        while (threadPoolExecutor.getActiveCount() != 0 && threadPoolExecutor.getQueue().size() != 0) {
            Thread.sleep(10000);
        }

        List<UserCollectionChainLog> geId = userCollectionChainLogDao.getByTypeAndStatusGeId(UserChainTypeEnum.TRANSFER, UserChainLogStatusEnum.WAIT, halfId);
        split = CollUtil.split(geId, 10000);
        for (List<UserCollectionChainLog> userCollectionChainLogs : split) {
            threadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    log.info("线程{}开始工作", Thread.currentThread().getId());
                    userCollectionChainLogs.forEach(userChainInfoService::transfer);
                }
            });
        }
        Thread.sleep(3000);
        while (threadPoolExecutor.getActiveCount() != 0 && threadPoolExecutor.getQueue().size() != 0) {
            Thread.sleep(10000);
        }
        log.info("完事儿");

    }

    /**
     * 藏品销毁
     *
     * @throws Exception
     */
    @XxlJob("burnNFT")
    public void burnNFT() throws Exception {
        List<UserCollection> userCollections = userCollectionDao.getBurnCollection();
        userCollections.forEach(userChainInfoService::burnNFT);
    }


    /**
     * 处理链回调
     */
    @XxlJob("chainCallback")
    public void chainCallback() throws Exception {
        List<ChainCallBackLog> list = chainCallBackLogDao.getListByStatus(ChainCallBackStatusEnum.TO_BE_PROCESSED, Boolean.TRUE);
        list.forEach(chainCallBackLog -> {
            try {
                userChainInfoService.chainCallback(chainCallBackLog);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
    }

    /**
     * 处理链回调超时
     * @throws Exception
     */
    @XxlJob("faultTolerantChainCallback")
    public void faultTolerantChainCallback() throws Exception {
        //获取超过1个小时的链回调
        List<ChainCallBackLog> list = chainCallBackLogDao.failListByOneHour();

        list.forEach(chainCallBackLog -> {
            try {
                userChainInfoService.faultTolerantChainCallback(chainCallBackLog);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });

    }



 



}
